package controllers

import (
	"anban/logic"
	"anban/models"
	"anban/service"
	"anban/utils"
	"anban/utils/wechat"
	"fmt"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"
	"net/url"
	"time"
)

type CommonRes struct {
	Error        int    `json:"error"`
	ErrorMessage string `json:"errorMessage"`
}

type Child struct {
	Id   string `json:"id"`
	Name string `json:"name"`
}

type WebUrl struct {
	CallUrl    string `json:"callUrl"`
	AboutUrl   string `json:"aboutUrl"`
	ServiceUrl string `json:"serviceUrl"`
	TravelUrl  string `json:"travelUrl"`
}

type BusBindRes struct {
	Error        int     `json:"error"`
	ErrorMessage string  `json:"errorMessage"`
	DeviceId     string  `json:"deviceId"`
	SchoolId     string  `json:"schoolId"`
	SchoolName   string  `json:"schoolName"`
	Buses        []Child `json:"buses"`
	WebUrl       WebUrl  `json:"webUrl"`
}

type TravelStartRes struct {
	Error        int    `json:"error"`
	ErrorMessage string `json:"errorMessage"`
	TravelId     string `json:"travelId"`
}

type TravelRunningRes struct {
	Error        int    `json:"error"`
	ErrorMessage string `json:"errorMessage"`
	Travel       Travel `json:"travel"`
}

type Travel struct {
	Id         string  `json:"id"`
	Start      int64   `json:"start"`
	End        int64   `json:"end"`
	UpPerson   int64   `json:"upPerson"`
	DownPerson int64   `json:"downPerson"`
	State      int     `json:"state"`
	BusId      string  `json:"busId"`
	BusName    string  `json:"busName"`
	MapUrl     string  `json:"mapUrl"`
	Students   []Child `json:"students"`
	Ons        []Child `json:"ons"`
	Reminds    []Child `json:"reminds"`
}

type BusInfosRes struct {
	Error        int        `json:"error"`
	ErrorMessage string     `json:"errorMessage"`
	Infos        []BusInfos `json:"infos"`
}

type BusInfos struct {
	Id        string `json:"id"`
	Type      string `json:"type"`
	Phone     string `json:"phone"`
	CartNum   string `json:"cartNum"`
	ClassId   string `json:"classId"`
	Name      string `json:"name"`
	ClassName string `json:"className"`
	Photo     string `json:"photo"`
	Sex       int    `json:"sex"`
}

type BusListRes struct {
	Error        int     `json:"error"`
	ErrorMessage string  `json:"errorMessage"`
	Buses        []Child `json:"buses"`
}

type Student struct {
	Lng         int64  `json:"lng"`
	Photo       string `json:"photo"`
	StudentId   string `json:"studentId"`
	Phone       string `json:"phone"`
	StudentName string `json:"studentName"`
	Lat         int64  `json:"lat"`
}

type MapStudentRes struct {
	Error        int       `json:"error"`
	ErrorMessage string    `json:"errorMessage"`
	Students     []Student `json:"students"`
}

type SchoolBusController struct {
	beego.Controller
}

func (c *SchoolBusController) Prepare() {
	c.EnableXSRF = false
}

// 设备激活绑定
func (c *SchoolBusController) Bind() {
	res := &BusBindRes{}
	userName := c.GetString("username")
	password := c.GetString("password")
	deviceCode := c.GetString("deviceCode")
	mac := c.GetString("mac")
	logs.Info("username:", userName, "password:", password, "deviceCode:", deviceCode, "mac:", mac)

	res.Buses = []Child{}

	if len(userName) <= 0 || len(password) <= 0 {
		res.Error = 1000
		res.ErrorMessage = "操作失败，请提供用户名或密码"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	p := map[string]interface{}{}
	p["relation"] = true
	p["username"] = userName
	p["password"] = password
	device := service.GetDeviceInfo(p)
	if device.Id <= 0 {
		res.Error = 1001
		res.ErrorMessage = "操作失败，请检查用户名或密码是否正确"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	res.Error = 0
	res.ErrorMessage = ""
	res.SchoolName = device.School.Name
	res.SchoolId = device.School.Sn
	res.DeviceId = device.Sn
	res.Buses = []Child{
		{Id: fmt.Sprintf("%d", device.Sn), Name: device.Place},
	}

	if device.BindStatus != 1 {
		input := url.Values{
			"id":          {fmt.Sprintf("%d", device.Id)},
			"bind_status": {"1"},
			"device_code": {deviceCode},
			"mac":         {mac},
		}
		service.EditDevice(input)
	}

	c.Data["json"] = res
	c.ServeJSON()
}

// 开始行程
func (c *SchoolBusController) TravelStart() {
	res := &TravelStartRes{}
	deviceSn := c.GetString("deviceId")

	p := map[string]interface{}{}
	p["sn"] = deviceSn
	device := service.GetDeviceInfo(p)
	if device.Id <= 0 {
		res.Error = 1002
		res.ErrorMessage = "系统中没有找到对应设备"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	input := url.Values{
		"device_id": {fmt.Sprintf("%d", device.Id)},
		"status":    {"1"},
	}
	travelId, err := service.AddTravel(input)
	if err != nil {
		res.Error = 1001
		res.ErrorMessage = "行程添加失败，请稍候重试"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	p = map[string]interface{}{}
	p["id"] = travelId
	travel := service.GetTravelInfo(p)
	if travel.Id <= 0 {
		res.Error = 1002
		res.ErrorMessage = "行程添加失败，请稍候重试"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}
	res.TravelId = travel.Sn

	c.Data["json"] = res
	c.ServeJSON()
}

// 行程恢复（正在进行）
func (c *SchoolBusController) TravelRunning() {
	res := &TravelRunningRes{}
	busId := c.GetString("busId")
	deviceSn := c.GetString("deviceId")

	res.Travel.Students = []Child{}

	p := map[string]interface{}{}
	p["sn"] = deviceSn
	device := service.GetDeviceInfo(p)
	if device.Id <= 0 {
		res.Error = 1000
		res.ErrorMessage = "系统中没有找到对应设备"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	p = map[string]interface{}{}
	p["deviceId"] = device.Id
	p["status"] = 1
	travel := service.GetTravelInfo(p)
	if travel.Id <= 0 {
		res.Error = 1001
		res.ErrorMessage = "没有正在进行中的行程"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	p = map[string]interface{}{}
	p["travelId"] = travel.Id
	studentCount, studentList := service.GetStudentList(p)

	res.Travel.Id = travel.Sn
	res.Travel.Start = travel.StartTime.Unix()
	res.Travel.UpPerson = studentCount
	if travel.Status == 1 {
		res.Travel.End = 0
		res.Travel.DownPerson = 0
		res.Travel.State = 0
	} else {
		res.Travel.End = travel.EndTime.Unix()
		res.Travel.DownPerson = studentCount
		res.Travel.State = 1
	}
	res.Travel.BusId = busId
	res.Travel.BusName = device.Place
	res.Travel.MapUrl = ""
	res.Travel.Ons = []Child{}
	res.Travel.Reminds = []Child{}
	
	var students []Child
	for _, student := range studentList {
		child := Child{
			Id:   student.Sn,
			Name: student.RealName,
		}
		students = append(students, child)
	}
	res.Travel.Students = students

	c.Data["json"] = res
	c.ServeJSON()
}

// 结束行程
func (c *SchoolBusController) TravelEnd() {
	res := &CommonRes{}
	travelSn := c.GetString("travelId")

	p := map[string]interface{}{}
	p["sn"] = travelSn
	travel := service.GetTravelInfo(p)
	if travel.Id <= 0 {
		res.Error = 1000
		res.ErrorMessage = "没有正在进行中的行程"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	p = map[string]interface{}{}
	p["relation"] = true
	p["travelId"] = travel.Id
	_, studentList := service.GetStudentList(p)
	time.AfterFunc(5 * time.Minute, func() {
		for _, student := range studentList {
			if student.IsAtSchoolBus == 1 {
				logic.SendAtBusNotice(student, "")
			}
		}
	})

	input := url.Values{
		"id":       {fmt.Sprintf("%d", travel.Id)},
		"status":   {"2"},
		"end_time": {time.Now().Format("2006-01-02 15:04:05")},
	}
	service.EditTravel(input)

	c.Data["json"] = res
	c.ServeJSON()
}

// 批量（手工）下车
func (c *SchoolBusController) TravelDown() {
	var input url.Values
	res := &CommonRes{}
	deviceSn := c.GetString("deviceId")
	travelSn := c.GetString("travelId")

	p := map[string]interface{}{}
	p["sn"] = deviceSn
	device := service.GetDeviceInfo(p)
	if device.Id <= 0 {
		res.Error = 1000
		res.ErrorMessage = "系统中没有找到对应设备"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	p = map[string]interface{}{}
	p["sn"] = travelSn
	travel := service.GetTravelInfo(p)
	if travel.Id <= 0 {
		res.Error = 1001
		res.ErrorMessage = "没有正在进行中的行程"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	p = map[string]interface{}{}
	p["travelId"] = travel.Id
	_, studentList := service.GetStudentList(p)

	for _, student := range studentList {
		p = map[string]interface{}{}
		p["deviceId"] = device.Id
		p["studentId"] = student.Id
		p["isDown"] = 0
		p["createdDate"] = time.Now().Format("2006-01-02")
		schoolBusNotice := service.GetSchoolBusNoticeInfo(p)

		if schoolBusNotice.Id > 0 {
			input = url.Values{
				"id":        {fmt.Sprintf("%d", schoolBusNotice.Id)},
				"is_down":   {"1"},
				"down_time": {time.Now().Format("2006-01-02 15:04:05")},
			}
			service.EditSchoolBusNotice(input)

			go c.SendNotice(student, "下车", "")
		}
	}

	c.Data["json"] = res
	c.ServeJSON()
}

// 上报gps
func (c *SchoolBusController) Gps() {
	var input url.Values
	res := &CommonRes{}
	lat := c.GetString("latitude")
	lng := c.GetString("longitude")
	travelSn := c.GetString("travelId")

	p := map[string]interface{}{}
	p["sn"] = travelSn
	travel := service.GetTravelInfo(p)
	if travel.Id <= 0 {
		res.Error = 1002
		res.ErrorMessage = "没有正在进行中的行程"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	input = url.Values{
		"id": {fmt.Sprintf("%d", travel.Id)},
		"lat": {lat},
		"lng": {lng},
	}
	service.EditTravel(input)

	c.Data["json"] = res
	c.ServeJSON()
}

// 上下车打卡上报
func (c *SchoolBusController) UploadLog() {
	var input url.Values
	res := &CommonRes{}
	directionMap := map[string]string{
		"false": "1",
		"true":  "2",
	}
	deviceSn := c.GetString("deviceId")
	schoolSn := c.GetString("schoolId")
	travelSn := c.GetString("travelId")
	cardNum := c.GetString("cardNum")
	isDown := c.GetString("isDown")
	direction := directionMap[isDown]
	temp := c.GetString("temp")
	fTemp := utils.Atof64(temp)
	temp = fmt.Sprintf("%.1f", fTemp)

	logs.Info("schoolBusUploadlog ", "cardNum:", cardNum, "deviceId:", deviceSn, "schoolId:", schoolSn, "isDown:", isDown, "travelId:", travelSn)
	if len(deviceSn) <= 0 || len(schoolSn) <= 0 || len(cardNum) <= 0 || len(isDown) <= 0 {
		res.Error = 1000
		res.ErrorMessage = "参数提供不完整"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	p := map[string]interface{}{}
	p["sn"] = deviceSn
	device := service.GetDeviceInfo(p)
	if device.Id <= 0 {
		res.Error = 1001
		res.ErrorMessage = "系统中没有找到对应设备"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}
	if device.BindStatus != 1 {
		res.Error = 1005
		res.ErrorMessage = "此设备还未绑定，无法使用"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	p = map[string]interface{}{}
	p["sn"] = schoolSn
	school := service.GetSchoolInfo(p)
	if school.Id <= 0 {
		res.Error = 1002
		res.ErrorMessage = "系统中没有找到对应学校"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	p = map[string]interface{}{}
	p["sn"] = cardNum
	p["relation"] = true
	student := service.GetStudentInfo(p)
	if student.Id <= 0 {
		res.Error = 1003
		res.ErrorMessage = "系统中没有找到对应学生"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}
	if student.Status == 0 {
		res.Error = 1004
		res.ErrorMessage = fmt.Sprintf("%s已被禁用", student.RealName)
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	p = map[string]interface{}{}
	p["sn"] = travelSn
	travel := service.GetTravelInfo(p)
	if travel.Id <= 0 {
		res.Error = 1005
		res.ErrorMessage = "行程没有开启"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	input = url.Values{
		"travel_id":  {fmt.Sprintf("%d", travel.Id)},
		"student_id": {fmt.Sprintf("%d", student.Id)},
	}
	service.AddTravelStudent(input)

	input = url.Values{
		"device_id":  {fmt.Sprintf("%d", device.Id)},
		"school_id":  {fmt.Sprintf("%d", school.Id)},
		"student_id": {fmt.Sprintf("%d", student.Id)},
		"device_sn":  {deviceSn},
		"school_sn":  {schoolSn},
		"card_num":   {cardNum},
		"direction":  {direction},
		"temp":       {temp},
	}
	service.AddMfbusUploadLog(input)

	remark := ""

	if school.IsUseSchoolBus == 1 {
		p = map[string]interface{}{}
		p["deviceId"] = device.Id
		p["studentId"] = student.Id
		p["isDown"] = 0
		p["createdDate"] = time.Now().Format("2006-01-02")
		schoolBusNotice := service.GetSchoolBusNoticeInfo(p)

		if schoolBusNotice.Id > 0 {
			if direction == "2" {
				input = url.Values{
					"id":        {fmt.Sprintf("%d", schoolBusNotice.Id)},
					"is_down":   {"1"},
					"down_time": {time.Now().Format("2006-01-02 15:04:05")},
				}
				service.EditSchoolBusNotice(input)

				input = url.Values{
					"id":        {fmt.Sprintf("%d", student.Id)},
					"is_at_school_bus":   {"0"},
				}
				service.EditStudent(input)

				go logic.SendSchoolBusNotice(student, "下车", remark)
			}
		} else {
			if direction == "1" {
				input = url.Values{
					"device_id":  {fmt.Sprintf("%d", device.Id)},
					"student_id": {fmt.Sprintf("%d", student.Id)},
					"is_up":      {"1"},
					"up_time":    {time.Now().Format("2006-01-02 15:04:05")},
				}
				service.AddSchoolBusNotice(input)

				input = url.Values{
					"student_id": {fmt.Sprintf("%d", student.Id)},
					"type":       {"2"},
				}
				service.AddNewNotice(input)

				input = url.Values{
					"id":        {fmt.Sprintf("%d", student.Id)},
					"is_at_school_bus":   {"1"},
				}
				service.EditStudent(input)

				go logic.SendSchoolBusNotice(student, "上车", remark)
			}
		}
	}

	if fTemp > 0 {

		var first string
		if direction == "1" {
			first = "您孩子到校体温异常"
		} else if direction == "2" {
			first = "您孩子离校体温异常"
		}

		input = url.Values{
			"id": {fmt.Sprintf("%d", student.Id)},
		}
		if fTemp > 37.0 {
			input["temp_is_normal"] = []string{"0"}

			if school.IsUseMobileMsg == 1 {
				go logic.SendTempAbnormalNotice(student, first, temp, "")
			}
		} else {
			input["temp_is_normal"] = []string{"1"}
		}
		service.EditStudent(input)

		if student.School.IsUseTemp == 1 {
			p = map[string]interface{}{}
			p["deviceId"] = device.Id
			p["studentId"] = student.Id
			p["isLeft"] = 0
			p["createdDate"] = time.Now().Format("2006-01-02")
			tempNotice := service.GetTempNoticeInfo(p)

			if tempNotice.Id > 0 {
				input = url.Values{
					"id":        {fmt.Sprintf("%d", tempNotice.Id)},
					"is_left":   {"1"},
					"left":      {time.Now().Format("2006-01-02 15:04:05")},
					"left_temp": {temp},
				}
				service.EditTempNotice(input)

				go logic.SendTempNotice(student, "离校体温通知", temp, "")
			} else {
				input = url.Values{
					"device_id":    {fmt.Sprintf("%d", device.Id)},
					"student_id":   {fmt.Sprintf("%d", student.Id)},
					"is_arrived":   {"1"},
					"arrived":      {time.Now().Format("2006-01-02 15:04:05")},
					"arrived_temp": {temp},
				}
				service.AddTempNotice(input)

				go logic.SendTempNotice(student, "到校体温通知", temp, "")
			}
		}
	}

	res.Error = 0
	res.ErrorMessage = ""
	c.Data["json"] = res
	c.ServeJSON()
}

func (c *SchoolBusController) SendNotice(student *models.Student, status string, remark string) {
	domain := beego.AppConfig.String("domain")
	path := beego.URLFor("parent.SchoolBusNoticeController.ShowList")
	wechatUrl := fmt.Sprintf("%s%s", domain, path)
	familySn := student.FamilySn
	if len(familySn) > 0 {
		p := map[string]interface{}{}
		p["familySn"] = familySn
		_, userList := service.GetUserList(p)
		for _, user := range userList {
			if user.SubscribeStatus == 1 && user.Status == 1 {
				wechat.SendSchoolBusNotice(user.OpenId, "您有新的校车通知", remark, wechatUrl, student.RealName, "无", status, time.Now().Format("2006-01-02 15:04:05"))
			}
		}
	}
}

// 获取学生信息
func (c *SchoolBusController) Infos() {
	res := &BusInfosRes{}
	cardNum := c.GetString("cardNum")
	schoolSn := c.GetString("schoolId")

	res.Infos = []BusInfos{}

	if len(cardNum) <= 0 && len(schoolSn) <= 0 {
		res.Error = 1000
		res.ErrorMessage = "请提供卡号或学校ID"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}
	sex := map[int]int{
		0: 1,
		1: 0,
	}

	if len(cardNum) > 1 {
		p := map[string]interface{}{}
		p["relation"] = true
		p["sn"] = cardNum
		student := service.GetStudentInfo(p)
		if student.Id <= 0 {
			res.Error = 1001
			res.ErrorMessage = fmt.Sprintf("卡号%s没有找到对应学生的信息")
			c.Data["json"] = res
			c.ServeJSON()
			return
		}

		res.Error = 0
		res.ErrorMessage = ""
		res.Infos = []BusInfos{
			{
				Id:        student.Sn,
				Type:      "S",
				Phone:     "",
				CartNum:   student.Sn,
				ClassId:   student.Class.Sn,
				Name:      student.RealName,
				ClassName: student.Class.Name,
				Photo:     "",
				Sex:       sex[student.Sex],
			},
		}

		c.Data["json"] = res
		c.ServeJSON()
		return
	}


	p := map[string]interface{}{}
	p["relation"] = true
	p["status"] = 1
	p["schoolSn"] = schoolSn
	_, studentList := service.GetStudentList(p)
	infos := []BusInfos{}
	for _, student := range studentList {
		t := BusInfos{
			Id:        student.Sn,
			Type:      "S",
			Phone:     "",
			CartNum:   student.Sn,
			ClassId:   student.Class.Sn,
			Name:      student.RealName,
			ClassName: student.Class.Name,
			Photo:     "",
			Sex:       sex[student.Sex],
		}
		infos = append(infos, t)
	}

	res.Infos = infos
	c.Data["json"] = res
	c.ServeJSON()
}

// 校车列表
func (c *SchoolBusController) BusList() {
	res := &BusListRes{}
	deviceSn := c.GetString("deviceId")

	p := map[string]interface{}{}
	p["sn"] = deviceSn
	device := service.GetDeviceInfo(p)
	if device.Id <= 0 {
		res.Error = 1000
		res.ErrorMessage = "系统中没有找到对应设备"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	res.Buses = []Child{
		{Id: device.Sn, Name: device.Place},
	}
	c.Data["json"] = res
	c.ServeJSON()
}

// 设备绑定校车
func (c *SchoolBusController) BusBind() {
	res := &BusListRes{}
	res.Buses = []Child{}
	c.Data["json"] = res
	c.ServeJSON()
}

// 当前gps位置附近学生
func (c *SchoolBusController) MapStudent() {
	res := &MapStudentRes{}
	res.Students = []Student{}
	c.Data["json"] = res
	c.ServeJSON()
}

// 设备注销
func (c *SchoolBusController) Unbind() {
	res := &UnbindRes{}
	userName := c.GetString("username")
	password := c.GetString("password")

	if len(userName) <= 0 || len(password) <= 0 {
		res.Error = 1000
		res.ErrorMessage = "操作失败，请提供用户名或密码"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	p := map[string]interface{}{}
	p["relation"] = true
	p["username"] = userName
	p["password"] = password
	device := service.GetDeviceInfo(p)
	if device.Id <= 0 {
		res.Error = 1001
		res.ErrorMessage = "操作失败，请检查用户名或密码是否正确"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}
	if device.BindStatus <= 0 {
		res.Error = 1002
		res.ErrorMessage = "操作失败，此设备没有绑定任何学校，无需解绑"
		c.Data["json"] = res
		c.ServeJSON()
		return
	}

	input := url.Values{
		"id":          {fmt.Sprintf("%d", device.Id)},
		"bind_status": {"0"},
		"device_code": {""},
		"mac":         {""},
	}
	service.EditDevice(input)

	res.Error = 0
	res.ErrorMessage = ""
	c.Data["json"] = res
	c.ServeJSON()
}
